//
//  ViewController.m
//  OCApp
//
//  Created by dafiger on 2021.03.11.
//  Copyright © 2021 dafiger. All rights reserved.
//

#import "ViewController.h"

#import <CommonCrypto/CommonHMAC.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSString *str = @"你好中国";
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    NSString *str2 = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    const char *ss1 = [str UTF8String];
    const char *ss2 = [str cStringUsingEncoding:NSUTF8StringEncoding];
    const void *ss3 = data.bytes;
    
    NSUInteger len = [data length];
    Byte *byteData = (Byte*)malloc(len);
    
    UInt8 *byteData2 = byteData;
    unsigned char *byteData3 = byteData;
    uint8_t *byteData4 = byteData;
    
    size_t num1 = 1;
    unsigned long num2 = num1;
    
    uint64_t allNum1 = 100;
    unsigned long long allNum2 = allNum1;
    
//    Byte *byteData = malloc(sizeof(Byte)*16);
//    memset(byteData, 0, 6);
//    memcpy(byteData, [data bytes], len);
//    [data getBytes:byteData length:len];
    
    NSLog(@"%zd, %lu, %lu, %lu, %zd, ",str.length, strlen(ss1), strlen(ss2), strlen(ss3), data.length);
    
    
//    co_launch(^{
//        // async downloadDataFromUrl
//        NSData *data = await(downloadDataFromUrl(url));
//
//        // async transform data to image
//        UIImage *image = await(imageFromData(data));
//
//        // set image to imageView
////        self.imageView.image = image;
//    });
    
    co_launch(^{
        //默认在当前线程进行调度
    });

    
    co_launch_onqueue(dispatch_get_global_queue(0, 0), ^{
        //在指定的队列中运行的协程
    });
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:YES];
    
//    [self request_test];
    [self request];
    [self testCoobjcPromise];
    [self testGenerator];
}

- (void)request_test {
    NSString *imgUrl = @"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3363295869,2467511306&fm=26&gp=0.jpg";
    
    NSURL *url = [NSURL URLWithString:imgUrl];
    
    // 配置缓存策略
    [NSURLSession sharedSession].configuration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
    
    NSURLSession *session = [NSURLSession sharedSession];
    
//    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//    request.HTTPMethod = @"post";
//    request.HTTPBody = [@"username=123&password=123" dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLSessionDataTask *task = [session dataTaskWithURL:url
                                        completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"data:%@\n %@", data, response);
//        if (error) {
//            [promise reject:error];
//        }
//        else{
//            [promise fulfill:co_tuple(data, response)];
//        }
    }];
    
//    [promise onCancel:^(COPromise * _Nonnull promise) {
//        [task cancel];
//    }];
    
    [task resume];
}

#pragma mark - 异步请求
- (void)request {
    NSString *imgUrl = @"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3363295869,2467511306&fm=26&gp=0.jpg";
    NSURLSession *session = [NSURLSession sharedSession];
    
    COPromise *promise = [session async_dataTaskWithURL:[NSURL URLWithString:imgUrl]];
    [promise then:^id _Nullable(id  _Nullable value) {
        NSLog(@"成功111------------");
        COTuple2 *result = (COTuple2 *)value;
        NSData *data = result[0];
//        NSData *data = [result objectAtIndex:0];
        if (data) {
            NSLog(@"%@", [NSThread currentThread]);
            dispatch_sync(dispatch_get_main_queue(), ^{
                self.imageView.image = [UIImage imageWithData:data];
//                UIImage *image = await([UIImage async_imageWithData:data]);
//                self.imageView.image = image;
            });
        }
        return nil;
    }];
    [promise catch:^(NSError * _Nonnull error) {
        NSLog(@"失败111------------%@",error);
    }];
    [promise onCancel:^(COPromise * _Nonnull promise) {
        NSLog(@"取消111------------");
    }];
//    [promise cancel];
    
    return;
    
    COCoroutine *co = co_launch(^{
//        NSData *data = await([NSURLConnection co_sendAsynchronousRequest:request response:nil error:nil]);
        
//        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imgUrl]];
//        NSData *data = await([[NSURLSession alloc] async_dataTaskWithRequest:request]);
        
        COTuple2 *result = await(promise);
//        NSData *data = result[0];
        NSData *data = [result objectAtIndex:0];
        
        NSError *error = co_getError();
        if(error){
            //处理错误信息
            NSLog(@"失败222------------%@",error);
        }else{
            NSLog(@"成功222------------");
        }
        // 已经取消
        if (co_isCancelled()) {
            NSLog(@"取消222------------");
            return;
        }
        
//        NSURLResponse *response = nil;
//        NSData *data = nil;
//        co_unpack(&data, &response) = await(promise);
        
        UIImage *image = await([UIImage async_imageWithData:data]);
        self.imageView.image = image;
        
//        self.imageView.image = [UIImage imageWithData:data];
    });
    
//    [co cancel];
}

#pragma mark - promise
- (void)testCoobjcPromise {
    COPromise *promise = [COPromise promise:^(COPromiseFulfill  _Nonnull fullfill, COPromiseReject  _Nonnull reject) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//            id result = @"异步任务结束";
//            fullfill(result);
            NSError *error = [NSError errorWithDomain:@"异步任务失败" code:-1001 userInfo:nil];
            reject(error);
        });
    } onQueue:dispatch_get_global_queue(0, 0)];
    
//    COPromise *thenPromise = [promise then:^id _Nullable(id  _Nullable value) {
//        return promise;
//    }];
    
    // 函数响应式编程
//    [promise then:^id _Nullable(id  _Nullable value) {
//        NSLog(@"成功：%@",value);
//        return nil;
//    }];
//    [promise catch:^(NSError * _Nonnull error) {
//        NSLog(@"失败：%@",error);
//    }];
    
    // 协程编程
    co_launch(^{
        // 主动取消
//        [promise cancel];
        [promise onCancel:^(COPromise * _Nonnull promise) {
            NSLog(@"isCancel");
        }];
        
        // 捕获异常
        [promise catch:^(NSError * _Nonnull error) {
//            NSLog(@"NSError");
            NSLog(@"捕获异常：%@",error);
        }];
        
        id result = await(promise);
        
        // 已经取消
        if (co_isCancelled()) {
            return;
        }
        
        // 延时
//        co_delay(6.0);
        
        if(!result) {
            NSError *error = co_getError();
            NSLog(@"失败：%@",error);
            BOOL isPromiseCancel = [COPromise isPromiseCancelled:error];
            NSLog(@"isPromiseCancel %d",isPromiseCancel);
            return;
        }
        NSLog(@"result = %@",result);
        
//        NSError *error = co_getError();
//        if (error) {
//            NSLog(@"失败：%@",error);
//        } else {
//            NSLog(@"成功：%@",result);
//        }
        
//        id result = await([self testPromiseReject]);
//        NSError *error = co_getError();
//        if(error) {
//            NSLog(@"Error = %@",error);
//        } else {
//            NSLog(@"result = %@",result);
//        }
    });
}

#pragma mark - 自定义promise
- (COPromise *)customPromise {
//    COPromise *promise = [COPromise promise];
//    [promise reject:error];
//    [promise fulfill:co_tuple(data, response)];
//    [promise onCancel:^(COPromise * _Nonnull promise) {
//        [task cancel];
//    }];
    
    return [COPromise promise:^(COPromiseFulfill  _Nonnull fullfill, COPromiseReject  _Nonnull reject) {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            reject([NSError errorWithDomain:@"aa" code:3 userInfo:@{}]);
        });
    }];
}

#pragma mark - GCD倒计时
- (COPromise *)testPromise {
    
    COPromise *promise = [COPromise new];
    
    
    dispatch_source_t timer = nil;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 0);
    dispatch_source_set_event_handler(timer, ^{
        [promise fulfill:@13];
        dispatch_source_cancel(timer);
    });
    dispatch_resume(timer);
    
    [promise onCancel:^(COPromise * _Nonnull promise) {
        dispatch_source_cancel(timer);
    }];
    
    return promise;
}

#pragma mark - Generator
- (void)testGenerator {
    COGenerator *generator = [[COGenerator alloc] initWithBlock:^{
        int index = 0;
        while(co_isActive()){
            yield_val(@(index));
            index++;
        }
    } onQueue:dispatch_get_global_queue(0, 0) stackSize:1024];
    
    co_launch(^{
        for(int i = 0; i < 10; i++){
            int val = [[generator next] intValue];
            NSLog(@"generator______value:%d",val);
        }
    });
}

@end
